#include "ISectionNumericalCalculator.h"
#include "DataStructure/Common/Real.h"
#include "SectionCalculator/StandardSectionTool.h"

using SG::Algebra::Point;
using SG::DataStructure::Common::Real;
using SG::DataStructure::FEM::PBARLData;
using SG::FEMSolver::Element::ISectionNumericalCalculator;

void ISectionNumericalCalculator::Mesh (const PBARLData& section, _OUT Meshes& meshes,int refineLevel) const
{
    Real w1{section.m_dimension[1]};
    Real w2{section.m_dimension[2]};
    Real w3{section.m_dimension[0]};
    Real t1{section.m_dimension[4]};
    Real t2{section.m_dimension[5]};
    Real t3{section.m_dimension[3]};

    int n{refineLevel + 1};
    int nt1{n};
    int nt2{n};
    int nt3{n};
    int nw1{n};
    int nw2{n};
    int nw3{2 * n};

    StandardSectionTool secMesh;
    Point point;
    int nodeId{0};
    int eleId{0};
    Meshes newMeshes;
    NodeSet newEdgeNodes;
    int numRepeatNodes{0};
    NodeSet edgeNodes;

    // 1st block
    point.m_y = -0.5 * w2;
    point.m_z = w3 - t2;
    secMesh.MeshRect (point, 0.5 * (w2 - t3), t2, nw2, nt2, nodeId, eleId, _OUT newMeshes, _OUT newEdgeNodes);
    secMesh.Merge (edgeNodes, numRepeatNodes, newMeshes, meshes, nodeId, eleId);
    secMesh.UpdateEdgeNodes (newEdgeNodes, numRepeatNodes, edgeNodes);

    // 2nd block
    point.m_y = 0.5 * t3;
    secMesh.MeshRect (point, -t3, t2, nt3, nt2, nodeId, eleId, _OUT newMeshes, _OUT newEdgeNodes);
    numRepeatNodes = 2 * nt2 + 1;
    secMesh.Merge (edgeNodes, numRepeatNodes, newMeshes, meshes, nodeId, eleId);
    secMesh.UpdateEdgeNodes (newEdgeNodes, numRepeatNodes, edgeNodes);

    // 3rd block
    point.m_y = 0.5 * w2;
    secMesh.MeshRect (point, -0.5 * (w2 - t3), t2, nw2, nt2, nodeId, eleId, _OUT newMeshes, _OUT newEdgeNodes);
    numRepeatNodes = 2 * nt2 + 1;
    secMesh.Merge (edgeNodes, numRepeatNodes, newMeshes, meshes, nodeId, eleId);
    secMesh.UpdateEdgeNodes (newEdgeNodes, numRepeatNodes, edgeNodes);

    // 4th block
    point.m_y = -0.5 * t3;
    point.m_z = t1;
    secMesh.MeshRect2 (point, t3, w3 - t1 - t2, nt3, nw3, nodeId, eleId, _OUT newMeshes, _OUT newEdgeNodes);
    numRepeatNodes = 2 * nt3 + 1;
    secMesh.Merge (edgeNodes, numRepeatNodes, newMeshes, meshes, nodeId, eleId);
    secMesh.UpdateEdgeNodes (newEdgeNodes, numRepeatNodes, edgeNodes);

    // 5th block
    point.m_z = 0.0;
    secMesh.MeshRect2 (point, t3, t1, nt3, nt1, nodeId, eleId, _OUT newMeshes, _OUT newEdgeNodes);
    numRepeatNodes = 2 * nt3 + 1;
    secMesh.Merge (edgeNodes, numRepeatNodes, newMeshes, meshes, nodeId, eleId);
    secMesh.UpdateEdgeNodes (newEdgeNodes, numRepeatNodes, edgeNodes);

    // 6th block
    point.m_y = -0.5 * w1;
    secMesh.MeshRect (point, 0.5 * (w1 - t3), t1, nw1, nt1, nodeId, eleId, _OUT newMeshes, _OUT newEdgeNodes);
    numRepeatNodes = 2 * nt1 + 1;
    secMesh.Merge (edgeNodes, numRepeatNodes, newMeshes, meshes, nodeId, eleId);
    secMesh.UpdateEdgeNodes (newEdgeNodes, numRepeatNodes, edgeNodes);

    // 7th block
    point.m_y = 0.5 * w1;
    secMesh.MeshRect (point, -0.5 * (w1 - t3), t1, nw1, nt1, nodeId, eleId, _OUT newMeshes, _OUT newEdgeNodes);
    numRepeatNodes = 2 * nt1 + 1;
    secMesh.Merge (edgeNodes, numRepeatNodes, newMeshes, meshes, nodeId, eleId);
}